Directive: v-something
<div id="app">
<h1>{{ message }}</h1>
<input v-model="message" type="text">
</div>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello World'
}
})
</script>
Often used directives:
v-model:双向绑定
v-if:从DOM树里删除/添加
v-show:增加class: disable
v-for:遍历,如
v-for="plan in plans"v-on:events (or @events):绑定事件,如下
<form action="00.html" v-on:submit="handleIt">events 包括click,hover,submit…- Event Modifier
v-on:click.stop="…": event.stopPropagation();v-on:submit.prevent="...": event.preventDefault();
**在event 后面其实是一个方法,也可以是一个简单的表达式。表达式可以识别data中的变量。**如下:
@click="count =+ 1"建议在Vue 里使用v-on 去绑定事件而不是在JS 中,因为这样JS 就可以专注业务,几乎不涉及DOM
- Event Modifier
Component
/*HTML*/
<div id="app">
<my-counter title="Like"></my-counter>
<my-counter title="Dislike"></my-counter>
</div>
/*Template*/
<template id="counterTemplate">
<div>
<span> {{ title }}: </span>
<button @click="count++"> {{ count }} </button>
</div>
</template>
/*Vue*/
<script>
Vue.component('my-counter', {
template: "#counterTemplate",
data: function(){
return {count: 0}
},
props: ['title']
})
var vm = new Vue({
el: "#app"
})
</script>
- Component 可以全局,也可以local写在new Vue里面
- Component 的数据一定要用function返回的形式表现
- 不要忘记实例化Vue
单向数据传递
Vue2.0 严格实行数据单向传递,数据只能从parent 流向child,不能在child 里修改props.
- 从Parent(Vue实例) 到Child(一般指component),以props 的形式进行
- 绑定: v-bind or :
- props: [’…’]
- 传下来的变量,如果要用在computed 等方法里面,记得要加this
- 从Child 到Parent,只能使用触发事件 (on & emit) 的方式
- v-on 可以直接作用在component 上面
- template 上
v-on:click触发一个事件,事件里通过this.$emit('example', data)触发example事件 - 在component 里面通过
v-on:example触发事件,在回调函数里接收 data
Computed vs Watch
<div id="app">
<p>Your Level: {{ level }}</p><br>
<button @click="points += 10">kill enermy</button>
<p>Experience: {{ points }}<p></p>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
points: 0
},
//in fact, watch can do the same thing.
//in most case, computed is prefered
computed: {
level: function(){
if(this.points <= 20) return 1;
if(this.points <= 50) return 2;
if(this.points <= 100) return 3;
if(this.points <= 150) return 4;
return "MAX";
}
}
})
Class
<div :class={active: isActive, error: hasError}:
如果isActive 属性为真,增加active 类;如果hasError 为真,增加error类。
或者:
<div :class=[activeClass, errorClass]></div>
<script>
...
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
</script>
Utils (Mixin)
如果有一些通用的Utils 方法或变量,可以通过Mixin 方法全局调用,如下
Vue.mixin({
methods: {
method1 () {
// do something
}
}
})
// in the component .vue
// simply use
... this.method1
Webpack
使用Notes\vue_learn\webpack+vue 里的配置
npm install; npm upadte
入口为src/main.js,基本模版为src/components/app.vue,出口为dist/main.js
利用webpack-dev-server -inline 进行live-load
详细内容见 webpack.md
在index.html 中引入bundle 文件和基本div
<div id="app"></div> <script src="dist/main.js"></script>在入口文件 main.js 中引入Vue 和 基本模版app
import Vue from "vue"; import app from "./components/app"; Vue.config.debug = true; new Vue(app);基本模版 app.vue 是编写网站的基础,所有的组件tag 都是用在这里面,例如
<script>
import hello from './hello.vue'; //引入组件
import list from './list.vue'; //引入组件
export default { //ES6默认导出
el: "#app", //band to #app in index.html 唯一接口
data: function () { //data,可以用ES6 写成 data () {}
return {
name: "Ethan",
age: 24
}
},
components: { //所有组件需要在这里注册才能使用
hello,
list
}
}
</script>
<template> //HTML 页面一样的写法
<div>
<h1>Name: {{ name }}</h1>
<h1>Age: {{ age }}</h1>
<hello></hello> //直接使用模版tag
<list></list>
</div>
</template>
<style lang="sass" rel="stylesheet/scss"> //CSS 使用SCSS 预编译
$qwe: blue;
body {
background-color: $qwe;
h1:hover {
height: 100px;
}
h2 {
background-color: #999;
}
}
</style>
- 其中的Hello 和List 都是组件,在
./src/conponents/hello.vue 和 list.vue中,例如list.vue:
<script>
export default{ //默认导出
data: function () { //直接写data,不需要el绑定
return {
lists: [
{name: "小红",age: 20},
{name: "张三",age: 12}]
}
}
}
</script>
<template>
<div>
<ul>
<li v-for="item in lists"> //正常vue directive 用法
<h3 class="name">NAME: {{ item.name }}</h3>
<h3 class="age">AGE: {{ item.age }}</h3>
</li>
</ul>
</div>
</template>
<style lang="sass" rel="stylesheet/scss">
...
</style>
Laravel
blade
因为blade 也用{{}} 模版,和Vue 有冲突,所以需要在Vue 的模版符号前加上@,如@
- 注意传来的JSON数据有可能需要用 JSON.parse() 解析一遍
- 使用Ajax 的时候,建议在created 函数里进行请求,并且把数据赋予对应的data
- 可以用jQuery请求Ajax,也可以用Vue-Resource 进行请求,非常方便
Filter
{{ msg | capitalize }} msg 全部大写
还有orderBy 功能,可以在v-for 的时候自动按照某一个属性进行排列limit-by
全部替换成javascript 在computed 中操作数据,如slice, lodash.orderby 等等
过滤器可以串联:
{{ message | filterA | filterB }} 过滤器是 JavaScript 函数,因此可以接受参数:{{ message | filterA(‘arg1’, arg2) }}
最重要的一点,filter 可以自定义
Vue.filter('customizedFilter', function(value, otherArgs){
... //such as newValue = captilize(value)
return newValue;
})
Vuex
Flux 构架就像眼睛,你自然会知道什么时候需要它
—— Vuex Website
Vuex 解决了传统单项数据流在大型应用中难以处理各种关系的问题,主要包括以下两点:
- 多个 view 同时依赖于某一个状态
- 来自不同 view 的行为需要更改同一个状态
决定我尝试 Vuex 的具体实例就是,利用 Firebase 做登陆的时候,几乎每个业务组件都需要获取用户的登录状态和用户信息,从而在用户登入登出时发生响应。实现这一点有三个做法
- 在每个组件里去调用
Firebase.auth去查询用户的登录情况 - 在 Root 组件里调用一次,然后通过 Props 传递给每一个子组件
- 通过 Vuex 集中管理状态,这样每个组件都可以通过
$states.currentUser去查询信息
Store
Vuex 的核心就是 Store ,也叫做一个容器,它包含着应用中大部分的 State。Vuex 和全局对象有两点不同:
- Vuex 的状态存储是响应式的,如果 state 发生变化,所有使用它的 view 都会改变
- 你不能直接改变 store 里的状态。唯一的改变途径就是显示的提交 mutation,这样可以方便的跟踪每一个状态的变化。
Libraries
How not to include a library in a Vue.js project?
##Global Variable
entry.js
window._ = require('lodash')
component.vue
export default {
created () {
console.log(_.isEmpty() ? 'Lodash loaded' : 'Not really')
}
}
Pros: easy to implement and use Cons: pollute global environment, not support server rendering
Import in every file
component…vue
import _ from 'lodash'
export default {
created () {
console.log(_.isEmpty() ? 'Lodash loaded' : 'Not really')
}
}
Pros: it works Cons: not dry and just a pain to copy that everywhere. crazy for maintenance
Prototype
entry.js
import moment from 'moment';
Object.defineProperty(Vue.prototype, '$moment', {value: moment});
component.vue
export default {
created () {
console.log('The time is ' + this.$moment().format('HH:mm'));
}
}
Pros: defineProperty defined property is read-only, $ make sure we follow the convention
Cons: need a liitle bit more knowledge